package org.ruoyi.data.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.utils.MapstructUtils;
import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.data.domain.DataTable;
import org.ruoyi.data.domain.DataTableColumn;
import org.ruoyi.data.domain.bo.DataHandleBo;
import org.ruoyi.data.domain.bo.DataTableBo;
import org.ruoyi.data.domain.vo.DataTableColumnVo;
import org.ruoyi.data.domain.vo.DataTableVo;
import org.ruoyi.data.mapper.DataHandleMapper;
import org.ruoyi.data.mapper.DataTableColumnMapper;
import org.ruoyi.data.mapper.DataTableMapper;
import org.ruoyi.data.service.IDataTableService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据Service业务层处理
 *
 * @author bz_huaYal9146
 * @date 2025-11-04
 */
@RequiredArgsConstructor
@Service
public class DataTableServiceImpl implements IDataTableService {

    private final DataTableMapper baseMapper;
    private final DataTableColumnMapper columnMapper;
    private final DataHandleMapper handleMapper;

    /**
     * 查询数据
     *
     * @param id 主键
     * @return 数据
     */
    @Override
    public DataTableVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询数据列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 数据分页列表
     */
    @Override
    public TableDataInfo<DataTableVo> queryPageList(DataTableBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DataTable> lqw = buildQueryWrapper(bo);
        lqw.orderByDesc(DataTable::getCreateTime);
        Page<DataTableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的数据列表
     *
     * @param bo 查询条件
     * @return 数据列表
     */
    @Override
    public List<DataTableVo> queryList(DataTableBo bo) {
        LambdaQueryWrapper<DataTable> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DataTable> buildQueryWrapper(DataTableBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DataTable> lqw = Wrappers.lambdaQuery();
        //lqw.orderByAsc(DataTable::getId);
        lqw.eq(StringUtils.isNotBlank(bo.getDataCode()), DataTable::getDataCode, bo.getDataCode());
        lqw.like(StringUtils.isNotBlank(bo.getDataTableName()), DataTable::getDataTableName, bo.getDataTableName());
        lqw.eq(StringUtils.isNotBlank(bo.getDataSql()), DataTable::getDataSql, bo.getDataSql());
        lqw.eq(StringUtils.isNotBlank(bo.getDataFormula()), DataTable::getDataFormula, bo.getDataFormula());
        return lqw;
    }

    /**
     * 新增数据
     *
     * @param bo 数据
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(DataTableBo bo) {
        DataTable add = MapstructUtils.convert(bo, DataTable.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改数据
     *
     * @param bo 数据
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(DataTableBo bo) {
        DataTable update = MapstructUtils.convert(bo, DataTable.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DataTable entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除数据信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public R deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
            LambdaQueryWrapper<DataTableColumn> lqw = new LambdaQueryWrapper<>();
            lqw.in(DataTableColumn::getDataTableId, ids);
            Long num = columnMapper.selectCount(lqw);
            if (num > 0) {
                return R.fail("先删除数据表的字段才能删除");
            }
        }
        return baseMapper.deleteBatchIds(ids) > 0 ? R.ok() : R.fail("删除失败");
    }

    @Override
    public R getData(DataHandleBo bo, boolean isTitle) {
        LambdaQueryWrapper<DataTable> lqw = new LambdaQueryWrapper<>();
        lqw.eq(DataTable::getDataCode, bo.getDataCode());
        DataTable dataTable = baseMapper.selectOne(lqw);
        if (dataTable != null) {
            LambdaQueryWrapper<DataTableColumn> lqwColumn = new LambdaQueryWrapper<>();
            lqwColumn.eq(DataTableColumn::getDataTableId, dataTable.getId());
            lqwColumn.orderByAsc(DataTableColumn::getDataSort);
            List<DataTableColumnVo> listColumn = columnMapper.selectVoList(lqwColumn);

            // 获取要执行的 SQL（这里假设来自 dataTable.getDataSql()）
            String sql = dataTable.getDataSql(); // 推荐从配置中读取，而不是写死 "select * from sys_data"
            if (CharSequenceUtil.isBlank(sql)) {
                return R.fail("未配置查询 SQL");
            }
            if (bo.getParam() != null) {
                sql += " " + bo.getParam();
            }
            if (dataTable.getDataGroup() != null) {
                sql += " " + dataTable.getDataGroup();
            }
            if (dataTable.getDataOrder() != null) {
                sql += " " + dataTable.getDataOrder();
            }
            if (dataTable.getDataLimit() != null) {
                sql += " " + dataTable.getDataLimit();
            }

            try {

                // 执行 SQL 查询，返回 List<Map<String, Object>>
                List<Map<String, Object>> resultList = handleMapper.executeQuery(sql);
                
                // 可选：结合 listColumn 做字段过滤或重命名（根据业务需要）
                // 例如只返回配置的字段
                if (CollUtil.isNotEmpty(listColumn)) {
                    List<String> allowedColumns = listColumn.stream()
                            .map(DataTableColumnVo::getDataColumnName) // 假设 columnName 是数据库字段名
                            .toList();
                    resultList = resultList.stream()
                            .map(map -> map.entrySet().stream()
                                    .filter(entry -> allowedColumns.contains(entry.getKey()))
                                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))
                            .toList();
                }
                // 构建字段中文标签（作为第一行）
                Map<String, Object> columnLabels = new LinkedHashMap<>();
                for (DataTableColumnVo col : listColumn) {
                    if (StrUtil.isNotBlank(col.getDataColumnName())) {
                        String label = StrUtil.blankToDefault(col.getDataColumnCn(), col.getDataColumnName());
                        columnLabels.put(col.getDataColumnName(), label);
                    }
                }

                // 将 columnLabels 插入到 resultList 的最前面
                List<Map<String, Object>> finalResultList = new ArrayList<>();
                if (isTitle) finalResultList.add(columnLabels);           // 第一行：字段说明
                finalResultList.addAll(resultList);         // 后续行：真实数据

                return R.ok(finalResultList);
            } catch (Exception e) {
                e.printStackTrace();
                return R.fail("查询失败：" + e.getMessage());
            }

        }
        return R.fail("查不到数据");
    }

    @Override
    public R getDataFormula(DataHandleBo bo) {
        LambdaQueryWrapper<DataTable> lqw = new LambdaQueryWrapper<>();
        lqw.eq(DataTable::getDataCode, bo.getDataCode());
        DataTable dataTable = baseMapper.selectOne(lqw);
        if (dataTable != null) {
            R r = R.ok();
            r.setData(dataTable.getDataFormula());
            return r;
        }
        return R.fail();
    }
}
